﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SemenQuest.SubWindows
{
    public partial class VerticalLabel : Label
    {
        [Category("Appearance")]
        [DefaultValue(0)]
        [Description("Angle of the text")]
        public Int32 RotateAngle
        {
            get { return _RotateAngle; }
            set
            {
                Int32 normalAngle = ((value % 360) + 360) % 360;
                if (_RotateAngle != normalAngle)
                {
                    _RotateAngle = normalAngle;
                    Invalidate();
                }
            }
        }
        private Int32 _RotateAngle = 0;

        protected override void OnPaint(PaintEventArgs e)
        {
            //1. get size of string and calculate shift of rotationpoint, so text won't 
            //   rotate outside the control area
            Func<Double, Double> DegToRad = (angle) => Math.PI * angle / 180.0;
            SizeF size = e.Graphics.MeasureString(this.Text, this.Font, this.Parent.Width);

            Double normaleRads = DegToRad(_RotateAngle);
            Int32 hSinTheta = (Int32)Math.Ceiling((size.Height * Math.Sin(normaleRads)));
            Int32 wCosTheta = (Int32)Math.Ceiling((size.Width * Math.Cos(normaleRads)));
            Int32 wSinTheta = (Int32)Math.Ceiling((size.Width * Math.Sin(normaleRads)));
            Int32 hCosTheta = (Int32)Math.Ceiling((size.Height * Math.Cos(normaleRads)));
            Int32 rotatedWidth = Math.Abs(hSinTheta) + Math.Abs(wCosTheta);
            Int32 rotatedHeight = Math.Abs(wSinTheta) + Math.Abs(hCosTheta);

            Int32 horizShift = 0;
            Int32 vertShift = 0;
            if (_RotateAngle >= 0 && _RotateAngle < 90)
            {
                horizShift = Math.Abs(hSinTheta);
            }
            else if (_RotateAngle >= 90 && _RotateAngle < 180)
            {
                horizShift = rotatedWidth;
                vertShift = Math.Abs(hCosTheta);
            }
            else if (_RotateAngle >= 180 && _RotateAngle < 270)
            {
                horizShift = Math.Abs(wCosTheta);
                vertShift = rotatedHeight;
            }
            else if (_RotateAngle >= 270 && _RotateAngle < 360)
            {
                vertShift = Math.Abs(wSinTheta);
            }

            //2. Take text alignment point into account
            float X = 0, Y = 0;
            String name = Enum.GetName(typeof(ContentAlignment), TextAlign);
            X = name.Contains("Center") ? (this.Width - rotatedWidth) / 2 :
                name.Contains("Right") ? this.Width - rotatedWidth : 
                0;
            Y = name.Contains("Middle") ? (this.Height - rotatedHeight) / 2 :
                name.Contains("Bottom") ? this.Height - rotatedHeight :
                0;

            //3. Draw string 
            using (Brush b = new SolidBrush(this.ForeColor))
            {
                e.Graphics.TranslateTransform(horizShift + X, vertShift + Y);
                e.Graphics.RotateTransform(_RotateAngle);
                e.Graphics.DrawString(this.Text, this.Font, b, 0, 0);
            }
        }
    }
}
